package se.webbzon.boltzmann;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontFormatException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import javax.media.j3d.Transform3D;
import javax.swing.JFrame;
import javax.vecmath.AxisAngle4d;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3d;
import javax.vecmath.Vector3f;

import se.webbzon.boltzmann.debug.Debug;
import se.webbzon.oschi01.font.HorizontalAlignment;
import se.webbzon.oschi01.font.VerticalAlignment;
import se.webbzon.oschi01.resourceset.ResourceSet;
import se.webbzon.oschi01.resourceset.ResourceSetLoaderException;
import se.webbzon.oschi01.textureset.Texture3D;
import se.webbzon.oschi01.textureset.Texture3DSetLoader;
import se.webbzon.oschi01.worldarea.WorldArea;
import se.webbzon.oschi01.worldcamera.AbstractWorldView;
import se.webbzon.oschi01.worldcamera.SimpleWorldRenderer;
import se.webbzon.oschi01.worldcamera.WorldCameraPane;
import se.webbzon.oschi01.worldcamera.WorldViewException;
import se.webbzon.oschi01.worldobject.WorldObject;
import se.webbzon.oschi01.worldobject.WorldStaticObject;
import se.webbzon.oschi01.worldobject.appearance.Appearance3D;
import se.webbzon.oschi01.worldobject.appearance.CubeAppearance3D;
import se.webbzon.oschi01.worldobject.appearance.DirectionalLightAppearance3D;
import se.webbzon.oschi01.worldobject.appearance.GroupAppearance3D;
import se.webbzon.oschi01.worldobject.appearance.SimpleAppearance3D;

public class LoadWindow extends JFrame {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1136906122227876138L;

	// The dimension of the window
	private static final Dimension d = new Dimension(640,360);
	
	// The projection input to the camera
	private static final Point3d from = new Point3d(0,0,12), to = new Point3d();
	private static final Vector3d up = new Vector3d(0,1,0);

	/*============================================================
	Constructors
	============================================================*/
	
	public LoadWindow(SimpleWorldRenderer renderer) {
		setTitle("Boltzmann's Adventure - The Steinein Struggle (Loading)");
		setResizable(false);
		try {
			AbstractWorldView view = renderer.openWorldView(d);
			add(view);
			view.getCamera().projectPerspective(from, to, up);
		} catch (WorldViewException e) {
			e.printStackTrace();
		} 
		
		Texture3DSetLoader tHaffy, tCube;
		Font font = null;
		tHaffy = new Texture3DSetLoader();
		tCube = new Texture3DSetLoader();
		try {
			// Load resources
			tHaffy.addFromURL(Main.class.getClassLoader().getResource("loader/haffy.png"));
			tCube.addFromURL(Main.class.getClassLoader().getResource("loader/cube.png"));
			URL fontUrl = Main.class.getClassLoader().getResource("fonts/blzee_plain.ttf");
			InputStream is = fontUrl.openStream();
			font = Font.createFont(Font.TRUETYPE_FONT, is).deriveFont(24f);
			is.close();
		} catch (ResourceSetLoaderException | IOException | FontFormatException e) {
			Debug.report(e);
		}
		
		WorldArea world = new WorldArea(0);
		world.createInstance(new RotatingCube(tCube.getResourceSet(), tHaffy.getResourceSet()));
		world.createInstance(new Light(new Vector3f(1,2,-3)));
		world.createInstance(new Light(new Vector3f(-3,0,-1)));
		world.createInstance(new Hud(font));
		renderer.getEngine().setWorld(world);
		
		pack();
		setLocationRelativeTo(null);
		setVisible(true);
	}
	
	/*============================================================
	Private Classes
	============================================================*/
	
	/** A rotating cube for the load-screen. **/
	private static final class RotatingCube extends WorldStaticObject {
		
		private double t = 0;

		public RotatingCube(ResourceSet<Texture3D> bg, ResourceSet<Texture3D> fg) {
			super(WorldObject.onStep, createAppearance(bg, fg));
			setPosition(0,-1,0);
		}
		
		@Override public void onStep(WorldArea world) {
			t += 1;
			setRotation(0, 1, 0, 10*Math.cos(t/50));
		}
		
		/** Creates the appearance of this rotating cube. **/
		private static final Appearance3D createAppearance(ResourceSet<Texture3D> bg, ResourceSet<Texture3D> fg) {
			List<Appearance3D> appearances = new ArrayList<Appearance3D>();
			CubeAppearance3D background = new CubeAppearance3D(0, SimpleAppearance3D.TEXTURE_REPEATING, false);
			CubeAppearance3D foreground = new CubeAppearance3D(0, SimpleAppearance3D.TEXTURE_REPEATING, false);
			background.setTextureSet(bg);
			background.setHRep(-1);
			foreground.setTextureSet(fg);
			foreground.setHRep(-1);
			Transform3D transform = new Transform3D();
			transform.setRotation(new AxisAngle4d(1,1,1,Math.PI/3));
			foreground.setTransform(transform);
			transform.setScale(0.9);
			background.setTransform(transform);
			appearances.add(background);
			appearances.add(foreground);
			return new GroupAppearance3D(appearances);
		}
		
	}
	
	/** A light for the load-screen. **/
	private static final class Light extends WorldStaticObject {
		
		public Light(Vector3f direction) {
			super(0,new DirectionalLightAppearance3D(direction, Color.white));
		}
		
	}
	
	/** A heads-up display and background for the load-screen. **/
	private static final class Hud extends WorldObject {
		
		private static final Color 	bgColor = new Color(220,220,255), 
									textColor = Color.gray;
		
		private final Font font;
		
		public Hud(Font font) {
			super(WorldObject.onPreDraw);
			this.font = font;
		}

		@Override public void onPreDraw(WorldArea world, WorldCameraPane background) {
			background.setColor(bgColor);
			background.fillRect(0, 0, d.width, d.height);
			
			background.setFont(font);	
			background.setHAlignment(HorizontalAlignment.CENTER);
			background.setVAlignment(VerticalAlignment.BOTTOM);
			int textX = d.width/2;
			background.setColor(Color.black);
			background.drawString("Boltzmann's Adventure", textX, 96);
			background.drawString("- The Steinein Struggle -", textX, 132);
			background.drawString("Loading...", textX, d.height-24);
			
			background.setColor(textColor);
			background.drawString("Boltzmann's Adventure", textX-1, 95);
			background.drawString("- The Steinein Struggle -", textX-1, 131);
			background.drawString("Loading...", textX-1, d.height-25);
		}
		
		
	}
	
}
